package laba6;

import interfaces.task6.IOUtils;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author yakimovich
 */
public class IOUtilsImpl implements IOUtils {

    @Override
    public void replaceChars(Reader reader, Writer writer, String string, String string1) {
        if (reader == null || writer == null) {
            throw new NullPointerException();
        }
        if (string != null && string1 != null && string.length() != string1.length()) {
            throw new IllegalArgumentException("inChars and outChars have different lenght");
        }
        try {
            int c;
            try {
                while ((c = reader.read()) != -1) {
                    if (string != null && string1 != null) {
                        int index = string.indexOf(c);
                        if (index != -1) {
                            c = string1.charAt(index);
                        }
                    }
                    writer.write(c);
                }
                writer.flush();
            } catch (IOException e) {
                System.out.println(e);
            }
        } finally {
            try {
                reader.close();
                writer.close();
            } catch (IOException e) {
                System.out.println(e);
            }
        }
    }
/////////////////////////////////////////////////////////////////////////////

    @Override
    public String[] findFiles(String string) {
        if (string.equals("")) {
            throw new IllegalArgumentException("File is not defined");
        }
        List<String> result = new ArrayList<>();
        findFileNested(string, "", result);
        return result.toArray(new String[0]);
    }

//////////////////////////////////////////////////////////////////////////////
    @Override
    public String[] findFiles(String string, String string1) {
        if (string.equals("")) {
            throw new IllegalArgumentException("File is not defined");
        }

        if (string1 == null) {
            return findFiles(string);
        }

        List<String> result = new ArrayList<>();
        findFileNested(string, string1, result);
        return result.toArray(new String[0]);
    }
    ///////////////////////////////////////////////////////////////////////////

    @Override
    public void copyFile(String string, String string1) {
        int i;
        FileInputStream fin;
        FileOutputStream fout;

        //Open the source file
        try {
            fin = new FileInputStream(string);
        } catch (FileNotFoundException e) {
            throw new IllegalArgumentException("Input File Not Found", e);
        }

        //Open the target file
        try {
            fout = new FileOutputStream(string1);
        } catch (FileNotFoundException e) {
            throw new IllegalArgumentException("Output File Not Found", e);
        }

        //Copy of the file
        try {
            do {
                i = fin.read();
                if (i != -1) {
                    fout.write(i);
                }
            } while (i != -1);
            fout.flush();
        } catch (IOException e) {
            System.out.println("Copy Error" + e);
            //Close resources
        } finally {
            try {
                fin.close();
                fout.close();
            } catch (IOException e) {
                System.out.println(e);
            }
        }
    }
//////////////////////////////////////////////////////////////////////////////////

    @Override
    public void copyFileBuffered(File file, File file1) {
        InputStream fin;
        OutputStream fout;
        int buffer = 1024;

        //Open the source file 
        try {
            fin = new BufferedInputStream(new FileInputStream(file), buffer);
        } catch (FileNotFoundException e) {
            throw new IllegalArgumentException("Input File Not Found", e);
        }

        //Open the target file
        try {
            fout = new BufferedOutputStream(new FileOutputStream(file1));
        } catch (FileNotFoundException e) {
            throw new IllegalArgumentException("Output File Not Found", e);
        }

        //Copy of the file
        int i;
        try {
            do {
                i = fin.read();
                if (i != -1) {
                    fout.write(i);
                }
            } while (i != -1);
             fout.flush();
        } catch (IOException e) {
            System.out.println("Copy Error" + e);
            //Close resources
        } finally {
            try {
                fin.close();
                fout.close();
            } catch (IOException e) {
                System.out.println(e);
            }
        }
    }
////////////////////////////////////////////////////////////////////////////

    @Override
    public void copyFileBest(String string, String string1) {
        FileChannel inChannel;
        FileChannel outChannel;
        try {
            inChannel = new FileInputStream(new File(string)).getChannel();
            outChannel = new FileOutputStream(new File(string1)).getChannel();
        } catch (FileNotFoundException e) {
            throw new IllegalArgumentException("Input File Not Found", e);
        }
        try {
            inChannel.transferTo(0, inChannel.size(), outChannel);
        } catch (IOException e) {
            System.out.println(e);
        } finally {
            try {
                if (inChannel != null) {
                    inChannel.close();
                }
                if (outChannel != null) {
                    outChannel.close();
                }
            } catch (IOException e) {
                System.out.println(e);
            }
        }
    }
////////////////////////////////

    private void findFileNested(String folder, String ext, List<String> listFiles) {
        File file = new File(folder);
        File[] arrFiles = file.listFiles();

        for (File f : arrFiles) {
            if (f.isFile()) {
                String path = f.getAbsolutePath();
                if (path.endsWith(ext)) {
                    listFiles.add(path);
                }
            } else if (f.isDirectory()) {
                findFileNested(f.getAbsolutePath(), ext, listFiles);
            }
        }
    }
}
